#include <linux/init.h>
#include <linux/module.h>
#include <linux/spi/spi.h>
#include "head.h"

unsigned int major;
struct class *cls;
struct device *dev;
struct spi_device *spi1 = NULL;
char code[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F}; // 数字
char which[] = {0x8, 0x4, 0x2, 0x1};                                        // 数码管

// 封装操作方法
int m74hc595_open(struct inode *inode, struct file *file)
{
    printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    return 0;
}

long m74hc595_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
    int i, ret;
    unsigned int num;
    char buf[2]; // 存储数字和哪一个数码管

    ret = copy_from_user(&num, (void *)arg, 4);
    if (ret)
    {
        printk("copy_from_user fail\n");
        return -EIO;
    }

    if (cmd == SENT_PEOPLE_COUNT)
    {
        // 1-9  1  10-99 12  100-999 123  1000-9999 1234
        for (i = 0; i < 4; i++) 
        {
            buf[0] = which[i];   //0
            buf[1] = code[num % 10];  //5
            spi_write(spi1, buf, sizeof(buf));
            num /= 10;  //0
            if(num == 0)
                break;
        }
    }

    return 0;
}

int m74hc595_close(struct inode *inode, struct file *file)
{
    printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    return 0;
}

// 定义操作方法结构体遍历并且初始化
struct file_operations fops = {
    .open = m74hc595_open,
    .unlocked_ioctl = m74hc595_ioctl,
    .release = m74hc595_close,
};

int m74hc595_probe(struct spi_device *spi)
{
    spi1 = spi;
    int ret;
    // 字符设备驱动注册
    major = register_chrdev(0, "m74hc595", &fops);
    if (major < 0)
    {
        printk("注册字符设备驱动失败\n");
        ret = major;
        goto out1;
    }
    printk("注册字符设备驱动成功\n");

    // 设备节点的创建
    // 向上提交目录
    cls = class_create(THIS_MODULE, "m74hc595");
    if (IS_ERR(cls))
    {
        printk("向上提交目录失败\n");
        ret = PTR_ERR(cls);
        goto out2;
    }
    printk("向上提交目录成功\n");

    // 向上提交设备节点
    dev = device_create(cls, NULL, MKDEV(major, 0), NULL, "m74hc595");
    if (IS_ERR(dev))
    {
        printk("向上提交设备节点信息失败\n");
        ret = PTR_ERR(dev);
        goto out3;
    }
    printk("向上提交设备节点信息成功\n");

    return 0;
out3:
    class_destroy(cls);
out2:
    unregister_chrdev(major, "m74hc595");
out1:
    return ret;
}
int m74hc595_remove(struct spi_device *spi)
{
    // 设备节点的销毁
    device_destroy(cls, MKDEV(major, 0));
    // 设备信息的注销
    class_destroy(cls);
    // 字符设备驱动注销
    unregister_chrdev(major, "m74hc595");

    printk("%s:%d\n", __FILE__, __LINE__);
    return 0;
}

// 设备树匹配表
struct of_device_id of_table[] = {
    {
        .compatible = "m74hc595",
    },
    {},
};
// 定义SPI对象并且初始化
struct spi_driver m74hc595 = {
    .probe = m74hc595_probe,
    .remove = m74hc595_remove,
    .driver = {
        .name = "m74hc595",
        .of_match_table = of_table,
    },
};
// 一键注册宏
module_spi_driver(m74hc595);
MODULE_LICENSE("GPL");